import os
import sys
import tkinter as tk
from tkinter import filedialog, messagebox, ttk, colorchooser
from PIL import Image, ImageTk, ImageDraw, ImageFont
import webbrowser
from pathlib import Path

class WatermarkApp:
    def __init__(self, root):
        self.root = root
        self.root.title("图片水印工具")
        self.root.geometry("1000x650")
        
        # 设置应用图标
        if getattr(sys, 'frozen', False):
            application_path = os.path.dirname(sys.executable)
            icon_path = os.path.join(application_path, "icon.ico")
        else:
            application_path = os.path.dirname(os.path.abspath(__file__))
            icon_path = os.path.join(application_path, "icon.ico")
        
        if os.path.exists(icon_path):
            self.root.iconbitmap(icon_path)
        
        # 变量初始化
        self.image_path = None
        self.original_image = None
        self.watermarked_image = None
        self.display_image = None
        self.watermark_text = tk.StringVar(value="我的水印")
        self.opacity = tk.IntVar(value=50)
        self.font_size = tk.IntVar(value=30)
        self.angle = tk.IntVar(value=45)
        self.density = tk.IntVar(value=5)
        self.text_color = "#FFD700"  # 默认金色
        self.selected_font = tk.StringVar(value="simhei.ttf")
        
        # 创建主框架
        self.main_frame = ttk.Frame(root)
        self.main_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        
        # 左侧面板
        self.left_panel = ttk.Frame(self.main_frame, width=250)
        self.left_panel.pack(side=tk.LEFT, fill=tk.Y, padx=(0, 10))
        
        # 右侧预览区域
        self.right_panel = ttk.Frame(self.main_frame)
        self.right_panel.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True)
        
        # 预览标签
        self.preview_frame = ttk.LabelFrame(self.right_panel, text="预览")
        self.preview_frame.pack(fill=tk.BOTH, expand=True)
        
        self.canvas = tk.Canvas(self.preview_frame, bg="white")
        self.canvas.pack(fill=tk.BOTH, expand=True)
        
        # 创建控件
        self._create_widgets()
        
    def _create_widgets(self):
        # 操作区域
        control_frame = ttk.LabelFrame(self.left_panel, text="操作")
        control_frame.pack(fill=tk.X, padx=5, pady=5)
        
        # 选择图片按钮
        ttk.Button(control_frame, text="选择图片", command=self.load_image).pack(fill=tk.X, padx=5, pady=5)
        
        # 水印设置
        watermark_frame = ttk.LabelFrame(self.left_panel, text="水印设置")
        watermark_frame.pack(fill=tk.X, padx=5, pady=5)
        
        # 水印文字
        ttk.Label(watermark_frame, text="水印文字:").pack(anchor=tk.W, padx=5, pady=(5, 0))
        ttk.Entry(watermark_frame, textvariable=self.watermark_text).pack(fill=tk.X, padx=5, pady=(0, 5))
        self.watermark_text.trace_add("write", lambda *args: self.update_preview())
        
        # 字体选择
        ttk.Label(watermark_frame, text="字体:").pack(anchor=tk.W, padx=5, pady=(5, 0))
        fonts = ["simhei.ttf", "simsun.ttc", "simkai.ttf", "msyh.ttc", "Arial.ttf"]
        font_combo = ttk.Combobox(watermark_frame, textvariable=self.selected_font, values=fonts, state="readonly")
        font_combo.pack(fill=tk.X, padx=5, pady=(0, 5))
        font_combo.bind("<<ComboboxSelected>>", lambda *args: self.update_preview())
        
        # 字体颜色
        ttk.Label(watermark_frame, text="字体颜色:").pack(anchor=tk.W, padx=5, pady=(5, 0))
        color_frame = ttk.Frame(watermark_frame)
        color_frame.pack(fill=tk.X, padx=5, pady=(0, 5))
        
        self.color_preview = tk.Label(color_frame, bg=self.text_color, width=3, relief="raised")
        self.color_preview.pack(side=tk.LEFT, padx=(0, 5))
        ttk.Button(color_frame, text="选择颜色", command=self.choose_color).pack(side=tk.LEFT, fill=tk.X, expand=True)
        
        # 不透明度
        ttk.Label(watermark_frame, text=f"不透明度: {self.opacity.get()}%").pack(anchor=tk.W, padx=5, pady=(5, 0))
        opacity_scale = ttk.Scale(watermark_frame, from_=10, to=100, variable=self.opacity, orient=tk.HORIZONTAL)
        opacity_scale.pack(fill=tk.X, padx=5, pady=(0, 5))
        opacity_scale.bind("<Motion>", lambda e: self.update_scale_label(e, "不透明度", self.opacity, "%"))
        opacity_scale.bind("<ButtonRelease-1>", lambda *args: self.update_preview())
        
        # 字体大小
        ttk.Label(watermark_frame, text=f"字体大小: {self.font_size.get()}").pack(anchor=tk.W, padx=5, pady=(5, 0))
        font_size_scale = ttk.Scale(watermark_frame, from_=10, to=100, variable=self.font_size, orient=tk.HORIZONTAL)
        font_size_scale.pack(fill=tk.X, padx=5, pady=(0, 5))
        font_size_scale.bind("<Motion>", lambda e: self.update_scale_label(e, "字体大小", self.font_size))
        font_size_scale.bind("<ButtonRelease-1>", lambda *args: self.update_preview())
        
        # 旋转角度
        ttk.Label(watermark_frame, text=f"旋转角度: {self.angle.get()}°").pack(anchor=tk.W, padx=5, pady=(5, 0))
        angle_scale = ttk.Scale(watermark_frame, from_=0, to=359, variable=self.angle, orient=tk.HORIZONTAL)
        angle_scale.pack(fill=tk.X, padx=5, pady=(0, 5))
        angle_scale.bind("<Motion>", lambda e: self.update_scale_label(e, "旋转角度", self.angle, "°"))
        angle_scale.bind("<ButtonRelease-1>", lambda *args: self.update_preview())
        
        # 水印密度
        ttk.Label(watermark_frame, text=f"水印密度: {self.density.get()}").pack(anchor=tk.W, padx=5, pady=(5, 0))
        density_scale = ttk.Scale(watermark_frame, from_=1, to=10, variable=self.density, orient=tk.HORIZONTAL)
        density_scale.pack(fill=tk.X, padx=5, pady=(0, 5))
        density_scale.bind("<Motion>", lambda e: self.update_scale_label(e, "水印密度", self.density))
        density_scale.bind("<ButtonRelease-1>", lambda *args: self.update_preview())
        
        # 保存按钮
        save_frame = ttk.Frame(self.left_panel)
        save_frame.pack(fill=tk.X, padx=5, pady=5)
        ttk.Button(save_frame, text="保存图片", command=self.save_image).pack(fill=tk.X, padx=5, pady=5)
        
        # 关于信息
        about_frame = ttk.Frame(self.left_panel)
        about_frame.pack(fill=tk.X, padx=5, pady=5, side=tk.BOTTOM)
        about_label = ttk.Label(about_frame, text="图片水印工具 v1.0", foreground="blue", cursor="hand2")
        about_label.pack(pady=5)
        about_label.bind("<Button-1>", lambda e: messagebox.showinfo("关于", "图片水印工具 v1.0\n一个简单的图片水印添加工具"))
    
    def update_scale_label(self, event, prefix, variable, suffix=""):
        """更新滑块上方的标签文本"""
        # 确保鼠标在滑块上移动时才更新
        widget = event.widget
        x = event.x
        if 0 <= x <= widget.winfo_width():
            for widget in self.left_panel.winfo_children():
                if isinstance(widget, ttk.LabelFrame) and widget.winfo_children():
                    for child in widget.winfo_children():
                        if isinstance(child, ttk.Label) and child.cget("text").startswith(prefix):
                            child.configure(text=f"{prefix}: {variable.get()}{suffix}")
                            break
    
    def choose_color(self):
        """选择水印颜色"""
        color = colorchooser.askcolor(initialcolor=self.text_color, title="选择水印颜色")[1]
        if color:
            self.text_color = color
            self.color_preview.config(bg=color)
            self.update_preview()
    
    def load_image(self):
        """加载图片"""
        file_path = filedialog.askopenfilename(
            title="选择图片",
            filetypes=[("图片文件", "*.jpg *.jpeg *.png *.bmp *.gif"), ("所有文件", "*.*")]
        )
        
        if file_path:
            try:
                self.image_path = file_path
                self.original_image = Image.open(file_path)
                self.update_preview()
                # 调整窗口大小
                self.root.geometry("")  # 重置窗口大小
            except Exception as e:
                messagebox.showerror("错误", f"无法加载图片: {str(e)}")
    
    def update_preview(self):
        """更新预览"""
        if self.original_image is None:
            return
        
        try:
            # 创建水印图片
            self.watermarked_image = self.add_watermark(self.original_image.copy())
            
            # 调整图像大小以适应画布
            self.display_image = self.resize_image_to_fit(self.watermarked_image)
            
            # 显示在画布上
            photo = ImageTk.PhotoImage(self.display_image)
            self.canvas.config(width=photo.width(), height=photo.height())
            self.canvas.delete("all")
            self.canvas.create_image(0, 0, anchor=tk.NW, image=photo)
            self.canvas.image = photo  # 保留引用
        except Exception as e:
            messagebox.showerror("错误", f"预览生成错误: {str(e)}")
    
    def add_watermark(self, image):
        """添加水印到图片"""
        if not self.watermark_text.get().strip():
            return image
        
        # 创建文字水印
        # 获取系统字体
        font_path = self.selected_font.get()
        try:
            # 尝试直接使用指定的字体文件
            font = ImageFont.truetype(font_path, self.font_size.get())
        except:
            try:
                # 如果直接使用失败，尝试从系统字体目录加载
                system_font_dir = os.path.join(os.environ['WINDIR'], 'Fonts')
                font = ImageFont.truetype(os.path.join(system_font_dir, font_path), self.font_size.get())
            except:
                # 如果仍然失败，使用默认字体
                font = ImageFont.load_default()
        
        # 创建一个与原图大小相同的透明图层
        txt_layer = Image.new('RGBA', image.size, (255, 255, 255, 0))
        draw = ImageDraw.Draw(txt_layer)
        
        # 解析颜色
        r, g, b = int(self.text_color[1:3], 16), int(self.text_color[3:5], 16), int(self.text_color[5:7], 16)
        
        # 计算水印文字的大小
        watermark_text = self.watermark_text.get()
        bbox = font.getbbox(watermark_text)
        text_width, text_height = bbox[2] - bbox[0], bbox[3] - bbox[1]
        
        # 水印的间距
        grid_size = max(text_width, text_height) * (11 - self.density.get()) // 5
        
        # 在图片上均匀分布水印
        for y in range(0, image.height, grid_size):
            for x in range(0, image.width, grid_size):
                # 计算每个水印的位置
                pos_x = x + (y % grid_size) // 2  # 错开排列
                pos_y = y
                
                # 绘制水印
                draw.text((pos_x, pos_y), watermark_text, fill=(r, g, b, int(255 * self.opacity.get() / 100)), font=font)
        
        # 如果需要旋转
        if self.angle.get() != 0:
            txt_layer = txt_layer.rotate(self.angle.get(), expand=1)
            
            # 裁剪到原始尺寸
            center_x, center_y = txt_layer.width // 2, txt_layer.height // 2
            left = center_x - image.width // 2
            top = center_y - image.height // 2
            txt_layer = txt_layer.crop((left, top, left + image.width, top + image.height))
        
        # 合并水印和原图
        if image.mode == 'RGBA':
            watermarked = Image.alpha_composite(image, txt_layer)
        else:
            # 如果原图不是RGBA模式，先转换
            image_rgba = image.convert('RGBA')
            watermarked = Image.alpha_composite(image_rgba, txt_layer)
        
        return watermarked
    
    def resize_image_to_fit(self, image):
        """调整图像大小以适应画布"""
        canvas_width = self.canvas.winfo_width() or 800
        canvas_height = self.canvas.winfo_height() or 600
        
        # 计算缩放比例
        width_ratio = canvas_width / image.width
        height_ratio = canvas_height / image.height
        ratio = min(width_ratio, height_ratio)
        
        # 如果图像已经小于画布，不进行缩放
        if ratio >= 1:
            return image
        
        # 缩放图像
        new_width = int(image.width * ratio)
        new_height = int(image.height * ratio)
        return image.resize((new_width, new_height), Image.LANCZOS)
    
    def save_image(self):
        """保存带水印的图片"""
        if self.watermarked_image is None:
            messagebox.showinfo("提示", "请先加载图片并添加水印")
            return
        
        save_path = filedialog.asksaveasfilename(
            title="保存图片",
            defaultextension=".png",
            filetypes=[
                ("PNG图片", "*.png"),
                ("JPEG图片", "*.jpg *.jpeg"),
                ("BMP图片", "*.bmp"),
                ("所有文件", "*.*")
            ],
            initialfile=f"watermarked_{os.path.basename(self.image_path)}" if self.image_path else "watermarked_image.png"
        )
        
        if save_path:
            try:
                # 保存水印图片
                if self.watermarked_image.mode == 'RGBA' and save_path.lower().endswith(('.jpg', '.jpeg')):
                    # JPEG不支持透明度，转换为RGB
                    rgb_image = self.watermarked_image.convert('RGB')
                    rgb_image.save(save_path)
                else:
                    self.watermarked_image.save(save_path)
                messagebox.showinfo("成功", f"图片已保存到:\n{save_path}")
            except Exception as e:
                messagebox.showerror("错误", f"保存图片时出错: {str(e)}")

def main():
    root = tk.Tk()
    app = WatermarkApp(root)
    root.mainloop()

if __name__ == "__main__":
    main() 